Skip to main content

Feature Engineering

Three features are engineered: Impression Rate (number of impressions / total cost), Click-Through Rate (CTR) (number of clicks / total impressions), and Conversion Rate (number of conversions / total clicks). There are some NaN and Inf values due to division by 0 in some cases – these are filled with 0.

Some Campaigns may be very cost effective at generating impressions, while some others may be attractive enough for potential customers to click through the impression, and some others still may be good at convincing a conversion in the customer.

Hence, it is imperative to maximize all three metrics collectively.

ads["Impression Rate"] = ads["Impressions"] / ads["Cost"]
ads["Click Through Rate"] = ads["Clicks"] / ads["Impressions"]
ads["Conversion Rate"] = ads["Conversions"] / ads["Clicks"]
ads = ads.fillna(0).replace([np.nan, np.inf, -np.inf], 0)
ads = ads[["Platform", "Campaign type", "Impression Rate", "Click Through Rate", "Conversion Rate"]]

The moving averages of these three quantities are found for lookback window and the latest trend values are considered for the algorithm. lookback is 30 by default so that the same budget allocation may be followed for the next 30 days, at the end of which new data will have to be fed into the tool to produce a new optimal portfolio.

def moving_average(df, value):
df[value + " moving avg"] = df[value].rolling(window=lookback).mean()
df[value + " moving avg"] = df[value + " moving avg"].fillna(df[value].iloc[0:30].mean())
return df

df = pd.DataFrame()
for campaign in ads["Campaign type"].unique():
temp = ads[ads["Campaign type"] == campaign]
temp = moving_average(temp, "Impression Rate")
temp = moving_average(temp, "Click Through Rate")
temp = moving_average(temp, "Conversion Rate")
df = pd.concat([df, temp])
df = df[["Date", "Platform", "Campaign type", "Impression Rate moving avg", "Click Through Rate moving avg", "Conversion Rate moving avg"]]